/**
 * 
 */
package cn.bigcontainer.alt.meta.dto;

import cn.bigcontainer.alt.common.entity.BigMap;
import cn.bigcontainer.alt.common.util.WoKit;
import cn.bigcontainer.alt.meta.exception.MException;
import cn.bigcontainer.alt.meta.extension.MFormLoader;
import cn.bigcontainer.alt.meta.extension.MFormSubmission;
import cn.bigcontainer.alt.meta.po.MApp;
import lombok.extern.slf4j.Slf4j;

import java.util.HashMap;
import java.util.Map;

/**
 * 单表单视图应用.该应用仅包含一个新建和修改视图.
 * @author cailei
 * @date 2017年6月12日
 */
@Slf4j
public class MBasicForm extends MAppDto {

	public MBasicForm(MApp app, BigMap<String, Object> req) {
		super(app);
		getObject().setRequest(req);
	}

	public MBasicForm(MApp app) {
		super(app);
	}

	public MBasicForm() {
		super();
	}

	private Map<String, MViewDto> formViews = new HashMap<>();

	public void setView(String viewType, MViewDto createView) {
		formViews.put(viewType, createView);
	}

	/**
	 *
	 * @param viewType
	 * @return
	 */
	public String getViewId(String viewType) {
		return this.getData().getString(MAppDto.PREFIX_VIEW + viewType);
	}

	/**
	 *
	 * @param viewType
	 * @param name
	 * @return
	 */
	protected MViewDto getView(String viewType, String name) {
		MViewDto v = formViews.get(viewType);
		if (v != null) {
			v.setApp(this);
			return v;
		}
		String id = getViewId(viewType);
		if (WoKit.isEmpty(id)) {
			throw new MException(MException.CRUD_VW, name);
		}
		for (MViewDto view : this.getViews()) {
			if (view.getId().equals(id)) {
				formViews.put(viewType, view);
				return view;
			}
		}
		throw new MException(MException.CRUD_NOVW, name);
	}

	private Map<String, MFormSubmission> formSubmissions = new HashMap<>();

	/**
	 *
	 * @param viewType
	 * @return
	 */
	private MFormSubmission getExtensionFormSubmission (String viewType) {
		if (formSubmissions.get(viewType) != null) {
			return formSubmissions.get(viewType);
		}
		String param = PREFIX_EXTENSION + MAppDto.PREFIX_VIEW + viewType + ".submit";
		String ex = getExtension(param);
		if (WoKit.isEmpty(ex)) {
			return null;
		}
		MFormSubmission formSubmission = null;
		if (WoKit.containsBean(ex)) {
			formSubmission = WoKit.getBean(MFormSubmission.class, ex);
		} else {
			formSubmission = WoKit.getBean(MFormSubmission.class, MFormSubmission.DEFAULT);
		}
		formSubmissions.put(viewType, formSubmission);
		return formSubmission;
	}

	/**
	 *
	 * @param fv
	 * @param viewType
	 * @param create
	 * @return 如果返回非空值，则表示不再执行后续表单提交的系统代码
	 */
	public MViewDto beforeSubmitForm (MViewDto fv, String viewType, Boolean create) {
		MFormSubmission ex = getExtensionFormSubmission(viewType);
		if (ex != null) {
			return ex.before(fv, create);
		}
		return null;
	}

	/**
	 *
	 * @param fv
	 * @param viewType
	 * @param create
	 */
	public void afterSubmitForm (MViewDto fv, String viewType, Boolean create) {
		MFormSubmission ex = getExtensionFormSubmission(viewType);
		if (ex != null) {
			ex.after(fv, create);
		}
	}

	private Map<String, MFormLoader> formLoaders = new HashMap<>();

	/**
	 *
	 * @param viewType
	 * @return
	 */
	private MFormLoader getExtensionFormLoader (String viewType) {
		if (formLoaders.get(viewType) != null) {
			return formLoaders.get(viewType);
		}
		String param = PREFIX_EXTENSION + MAppDto.PREFIX_VIEW + viewType + ".load";
		String ex = getExtension(param);
		if (WoKit.isEmpty(ex)) {
			return null;
		}
		MFormLoader formSubmission = null;
		if (WoKit.containsBean(ex)) {
			formSubmission = WoKit.getBean(MFormLoader.class, ex);
		} else {
			formSubmission = WoKit.getBean(MFormLoader.class, MFormLoader.DEFAULT);
		}
		formLoaders.put(viewType, formSubmission);
		return formSubmission;
	}

	/**
	 * @param fv
	 * @return
	 */
	public MViewDto beforeLoadForm (MViewDto fv, String keyValue, String viewType, Boolean create) {
		MFormLoader ex = getExtensionFormLoader(viewType);
		if (ex != null) {
			return ex.before(fv, keyValue, create);
		}
		return null;
	}

	/**
	 * @param fv
	 * @return
	 */
	public void afterLoadForm (MViewDto fv, String keyValue, String viewType, Boolean create) {
		MFormLoader ex = getExtensionFormLoader(viewType);
		if (ex != null) {
			ex.after(fv, keyValue, create);
		}
	}

}
